package com.ljk.encrypt;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSON;
import com.ljk.encrypt.constant.ProviderServiceTypeEnum;
import com.ljk.util.string.Base64Util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.List;

public class AesUtil {


    /**
     * 列出当前Java环境中所有支持的 KeyGenerator 秘钥生成。
     *
     * @return 包含所有支持的 KeyGenerator 名称的列表
     */
    public static List<String> listKeyGenerator() {
        return EncryptUtil.listProviderService(ProviderServiceTypeEnum.KeyGenerator);
    }

    /**
     * 生成AES密钥
     *
     * @return Base64编码的AES密钥字符串
     */
    public static String generateAesKey() {
        return generateAesKey(128);
    }

    /**
     * 生成AES密钥
     *
     * @param keyLength 密钥长度  密钥长度只能是 128, 192 或 256 位
     * @return Base64编码的AES密钥字符串
     */
    public static String generateAesKey(int keyLength) {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(keyLength);
            SecretKey secretKey = keyGen.generateKey();
            return Base64Util.base64EncodeToString(secretKey.getEncoded());
        } catch (RuntimeException | NoSuchAlgorithmException e) {
            throw new RuntimeException("AES key generation failed", e);
        }
    }

    public static String generateAesKeySecureRandom(int keyLength) {
        // 选择密钥长度 (16字节=128位, 24字节=192位, 32字节=256位)
        int keySize; // 256位
        if (keyLength == 128) {
            keySize = 16;
        } else if (keyLength == 192) {
            keySize = 24;
        } else if (keyLength == 256) {
            keySize = 32;
        } else {
            throw new RuntimeException("AES key length is 128 or 192 or 256");
        }
        // 使用 SecureRandom 生成随机字节
        byte[] keyBytes = new byte[keySize];
        new SecureRandom().nextBytes(keyBytes);
        // 创建 SecretKeySpec
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        return Base64Util.base64EncodeToString(secretKey.getEncoded());
    }


    public static void main(String[] args) {
//        String s = generateAesKeySecureRandom(128);
//        System.out.println("s = " + s + "|" + s.length());
        List<String> str = EncryptUtil.listProviderService(ProviderServiceTypeEnum.Cipher);
        str.stream().filter(s -> s.contains("AES")).forEach(System.out::println);
        String key128 = generateAesKey(128);
        String key192 = generateAesKey(192);
        String key256 = generateAesKey(256);
        System.out.printf("key128 = %s , length = %s\r\n", key128, key128.length());
        System.out.printf("key192 = %s , length = %s\r\n", key192, key192.length());
        System.out.printf("key256 = %s , length = %s\r\n", key256, key256.length());
        System.out.println("aesEncrypt = " + aesEncrypt("123456", key192));

        //25.3.28记  aes 在jdk的实现不全,需要额外引入oracle的jdk包才能实现,所以只能自行实现或者采用第三方的工具包,
        //我选择使用hutool的加密模块完成,此类不再完善

    }

    /**
     * AES对称加密
     *
     * @param input 待加密字符串
     * @param key   加密密钥
     * @return 加密后的字符串
     */
    public static String aesEncrypt(String input, String key) {
        try {
            byte[] keyBytes = Base64Util.base64Decode(key);
            Key secretKey = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedBytes = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException("AES encryption failed", e);
        }
    }

    private static int convertKeyLength(int keyLength) {
        switch (keyLength) {
            case 16:
                return 128;
            case 24:
                return 192;
            case 32:
                return 256;
            default:
                throw new RuntimeException("AES key length is not correct");
        }
    }

    /**
     * AES对称解密
     *
     * @param input 待解密字符串
     * @param key   解密密钥
     * @return 解密后的字符串
     */
    public static String aesDecrypt(String input, String key) {
        try {
            byte[] keyByte = Base64Util.base64Decode(key);
            Key secretKey = new SecretKeySpec(keyByte, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(input));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("AES decryption failed", e);
        }
    }


}
